<html>
<head><meta charset="utf-8"><title>pre-releases · t-cargo/PubGrub · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/260232-t-cargo/PubGrub/index.html">t-cargo/PubGrub</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/260232-t-cargo/PubGrub/topic/pre-releases.html">pre-releases</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="246348254"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/260232-t-cargo/PubGrub/topic/pre-releases/near/246348254" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthieu Pizenberg <a href="https://rust-lang.github.io/zulip_archive/stream/260232-t-cargo/PubGrub/topic/pre-releases.html#246348254">(Jul 17 2021 at 22:49)</a>:</h4>
<p>I have some thoughts regarding pre-release versions, and I'll just throw them out here, see what you think.</p>
<p>When I tried the <code>Interval</code> approach (<a href="https://github.com/pubgrub-rs/pubgrub/pull/99">https://github.com/pubgrub-rs/pubgrub/pull/99</a>), you identified a problem with the <code>contains</code> function.<br>
It not being "pure" by potentially returning different results depending on the interpretation of bounds (is there a pre-release marker in a bound?) can mess up with backtracking.<br>
That problem logically arises because we are not being "mathematically strict" (hand waving) about the definition of our sets of versions.<br>
I was mixing the set of pre-releases and the set of normal versions into one unique ordered set of versions, which is not correct with the semantics of the <code>contains</code> function.<br>
If I remember well, in your range trait approach, you solved that problem by duplicating the normal versions, and pre-release versions, and duplicating the code for <code>contains</code> and <code>intersection</code>.</p>
<p>The thing I was trying to solve with the <code>Interval</code> approach was preventing users of pubgrub to have to implement their own <code>intersection</code> function.<br>
But by letting them implement <code>contains</code>, I introduced a flaw.</p>
<p>The question I'm now asking myself is the following.<br>
Can we have a system, where <code>contains</code> and <code>intersection</code> are rigorously implemented by ourselves, stricly based on some kind of interval bounds, but where our space for versions is not 1-dimensional, but can be multi-dimensional, like 1D for normal versions and 1D for pre-release versions.<br>
We can still have a 1D approximation for humans, but just for ease of notation.<br>
So for example "&gt;= 1.0-alpha2" would actually be the 2D specification <code>{ normal: "&gt;= 1.0", pre: "&gt;= 1.0-alpha2" }</code>.<br>
And "&gt;= 2.0" would be <code>{ normal: "&gt;= 2.0", pre: empty }</code>.</p>
<p>For <code>contains</code>, we could easily make a canonical implementation as follows.</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">fn</span> <span class="nf">contains</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">set</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">singleton</span><span class="p">(</span><span class="n">x</span><span class="p">).</span><span class="n">intersection</span><span class="p">(</span><span class="n">set</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">singleton</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>For <code>intersection</code> to be implementable by ourselves, we need to be able to access each parallel dimension.<br>
But each dimension may have versions of a different type so I don't know how we could define such things.</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">MultiDimRange</span><span class="o">&lt;</span><span class="k">const</span><span class="w"> </span><span class="n">D</span>: <span class="kt">usize</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">dimensions</span>: <span class="p">[</span><span class="n">Range</span><span class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span class="n">Interval</span><span class="o">&gt;</span><span class="p">;</span><span class="w"> </span><span class="n">D</span><span class="p">]</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>Is there a way to correctly write the struct above?</p>
<p>Alternatively, we could make concrete 2D, 3D etc implementations.<br>
Constraints semantics could easily reach 3D with things like normal + pre-release + long-term-support for example, where normal releases are to LTS releases what pre-releases are to normal releases.<br>
So I would not feel very comfortable manually writing a few and deciding when to stop.</p>
<p>Anyway, that was my random thoughts of today on the pre-release subject.</p>



<a name="246392473"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/260232-t-cargo/PubGrub/topic/pre-releases/near/246392473" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Eh2406 <a href="https://rust-lang.github.io/zulip_archive/stream/260232-t-cargo/PubGrub/topic/pre-releases.html#246392473">(Jul 18 2021 at 18:45)</a>:</h4>
<p>That all makes sense.</p>
<blockquote>
<p>If I remember well, in your range trait approach, you solved that problem by duplicating the normal versions, and pre-release versions, and duplicating the code for contains and intersection.</p>
</blockquote>
<p>Theoretically Yes. But in practice the implementation was just a wrapper around two <code>Pubgrub::Ranges</code>, so the implementation was just "delegate to the correct one". <a href="https://gist.github.com/Eh2406/88b8c799be3f3a6589073e8e58504a11#file-main-rs-L151">link</a><br>
It is probably worth looking into generalizations of that. Like a <code>TwoRange</code> who's <code>new(l: RS, r: RS, is_r: Fn(&amp;RS::VERSION) -&gt; bool) where RS: RangeSet</code>. Or a <code>EitherRange</code> who's that can have a <code>VERSION = Either</code> from the Either crate.</p>
<p>If it is true that is possible to build composable wrappers that implement <code>RangeSet</code> if there arguments do, and we can provide the most common building blocks in PubGrub, then I am not as bothered by how tricky it is to imple <code>RangeSet</code> by hand.</p>



<a name="246411133"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/260232-t-cargo/PubGrub/topic/pre-releases/near/246411133" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Eh2406 <a href="https://rust-lang.github.io/zulip_archive/stream/260232-t-cargo/PubGrub/topic/pre-releases.html#246411133">(Jul 19 2021 at 02:37)</a>:</h4>
<p>So I gave it a try, and here is a POC of a 2D using <code>Either</code>:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="c1">// use https://docs.rs/either/1.6.1/either/ next</span>
<span class="cp">#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">enum</span> <span class="nc">Either</span><span class="o">&lt;</span><span class="n">L</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">Left</span><span class="p">(</span><span class="n">L</span><span class="p">),</span><span class="w"></span>
<span class="w">    </span><span class="n">Right</span><span class="p">(</span><span class="n">R</span><span class="p">),</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;</span><span class="n">L</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&gt;</span><span class="w"> </span><span class="n">std</span>::<span class="n">fmt</span>::<span class="n">Display</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">Either</span><span class="o">&lt;</span><span class="n">L</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">fmt</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">formatter</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">std</span>::<span class="n">fmt</span>::<span class="n">Formatter</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">std</span>::<span class="n">fmt</span>::<span class="nb">Result</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="s">"TODO"</span><span class="p">.</span><span class="n">fmt</span><span class="p">(</span><span class="n">formatter</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="cp">#[derive(Debug, PartialEq, Eq, Clone)]</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">EitherSet</span><span class="o">&lt;</span><span class="n">L</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">left</span>: <span class="nc">L</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">right</span>: <span class="nc">R</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;</span><span class="n">L</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&gt;</span><span class="w"> </span><span class="n">std</span>::<span class="n">fmt</span>::<span class="n">Display</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">EitherSet</span><span class="o">&lt;</span><span class="n">L</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">fmt</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">formatter</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">std</span>::<span class="n">fmt</span>::<span class="n">Formatter</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">std</span>::<span class="n">fmt</span>::<span class="nb">Result</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="s">"TODO"</span><span class="p">.</span><span class="n">fmt</span><span class="p">(</span><span class="n">formatter</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;</span><span class="n">L</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&gt;</span><span class="w"> </span><span class="n">RangeSet</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">EitherSet</span><span class="o">&lt;</span><span class="n">L</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&gt;</span><span class="w"></span>
<span class="k">where</span><span class="w"></span>
<span class="w">    </span><span class="n">L</span>: <span class="nc">RangeSet</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">R</span>: <span class="nc">RangeSet</span><span class="p">,</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">type</span> <span class="nc">VERSION</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Either</span><span class="o">&lt;</span><span class="n">L</span>::<span class="n">VERSION</span><span class="p">,</span><span class="w"> </span><span class="n">R</span>::<span class="n">VERSION</span><span class="o">&gt;</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="k">fn</span> <span class="nf">none</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">left</span>: <span class="nc">L</span>::<span class="n">none</span><span class="p">(),</span><span class="w"></span>
<span class="w">            </span><span class="n">right</span>: <span class="nc">R</span>::<span class="n">none</span><span class="p">(),</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">fn</span> <span class="nf">any</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">left</span>: <span class="nc">L</span>::<span class="n">any</span><span class="p">(),</span><span class="w"></span>
<span class="w">            </span><span class="n">right</span>: <span class="nc">R</span>::<span class="n">any</span><span class="p">(),</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">fn</span> <span class="nf">exact</span><span class="p">(</span><span class="n">v</span>: <span class="nc">impl</span><span class="w"> </span><span class="nb">Into</span><span class="o">&lt;</span><span class="bp">Self</span>::<span class="n">VERSION</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">match</span><span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">into</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">Either</span>::<span class="n">Left</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">left</span>: <span class="nc">L</span>::<span class="n">exact</span><span class="p">(</span><span class="n">v</span><span class="p">),</span><span class="w"></span>
<span class="w">                </span><span class="n">right</span>: <span class="nc">R</span>::<span class="n">none</span><span class="p">(),</span><span class="w"></span>
<span class="w">            </span><span class="p">},</span><span class="w"></span>
<span class="w">            </span><span class="n">Either</span>::<span class="n">Right</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">left</span>: <span class="nc">L</span>::<span class="n">none</span><span class="p">(),</span><span class="w"></span>
<span class="w">                </span><span class="n">right</span>: <span class="nc">R</span>::<span class="n">exact</span><span class="p">(</span><span class="n">v</span><span class="p">),</span><span class="w"></span>
<span class="w">            </span><span class="p">},</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">fn</span> <span class="nf">negate</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">left</span>: <span class="nc">self</span><span class="p">.</span><span class="n">left</span><span class="p">.</span><span class="n">negate</span><span class="p">(),</span><span class="w"></span>
<span class="w">            </span><span class="n">right</span>: <span class="nc">self</span><span class="p">.</span><span class="n">right</span><span class="p">.</span><span class="n">negate</span><span class="p">(),</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">fn</span> <span class="nf">intersection</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">other</span>: <span class="kp">&amp;</span><span class="nc">Self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">left</span>: <span class="nc">self</span><span class="p">.</span><span class="n">left</span><span class="p">.</span><span class="n">intersection</span><span class="p">(</span><span class="o">&amp;</span><span class="n">other</span><span class="p">.</span><span class="n">left</span><span class="p">),</span><span class="w"></span>
<span class="w">            </span><span class="n">right</span>: <span class="nc">self</span><span class="p">.</span><span class="n">right</span><span class="p">.</span><span class="n">intersection</span><span class="p">(</span><span class="o">&amp;</span><span class="n">other</span><span class="p">.</span><span class="n">right</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="sd">/// Check if a range contains a given version.</span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">contains</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">version</span>: <span class="kp">&amp;</span><span class="nc">Self</span>::<span class="n">VERSION</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">bool</span> <span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">match</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">Either</span>::<span class="n">Left</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">left</span><span class="p">.</span><span class="n">contains</span><span class="p">(</span><span class="n">v</span><span class="p">),</span><span class="w"></span>
<span class="w">            </span><span class="n">Either</span>::<span class="n">Right</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">right</span><span class="p">.</span><span class="n">contains</span><span class="p">(</span><span class="n">v</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>One can build a 3D using <code>EitherSet&lt;A,  EitherSet&lt;B, C&gt;&gt;</code>, but I don't know how good the ergonomics are.</p>



<a name="246425886"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/260232-t-cargo/PubGrub/topic/pre-releases/near/246425886" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthieu Pizenberg <a href="https://rust-lang.github.io/zulip_archive/stream/260232-t-cargo/PubGrub/topic/pre-releases.html#246425886">(Jul 19 2021 at 07:54)</a>:</h4>
<p>Interesting, that's relatively straightforward indeed, and I wonder if it could be even shorter with the Interval API and the right amount of automatically derived impls</p>



<a name="246425959"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/260232-t-cargo/PubGrub/topic/pre-releases/near/246425959" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthieu Pizenberg <a href="https://rust-lang.github.io/zulip_archive/stream/260232-t-cargo/PubGrub/topic/pre-releases.html#246425959">(Jul 19 2021 at 07:55)</a>:</h4>
<p>I'll leave that thought for later since I'll still have to fix the bugs in the Interval approach first</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>